package com.novel.system.service.impl;

import com.novel.common.constants.UserConstants;
import com.novel.common.utils.StringUtils;
import com.novel.system.domain.SysMenu;
import com.novel.system.domain.SysRole;
import com.novel.system.domain.SysUser;
import com.novel.system.domain.vo.MenuVo;
import com.novel.system.domain.vo.MetaVo;
import com.novel.system.domain.vo.TreeData;
import com.novel.system.mapper.SysMenuMapper;
import com.novel.system.service.SysMenuService;
import org.springframework.stereotype.Service;

import java.util.*;

/**
 * 菜单 业务层处理
 *
 * @author novel
 * @date 2019/5/8
 */
@Service
public class SysMenuServiceImpl implements SysMenuService {
    private final SysMenuMapper menuMapper;

    public SysMenuServiceImpl(SysMenuMapper menuMapper) {
        this.menuMapper = menuMapper;
    }


    @Override
    public List<MenuVo> selectMenuList() {
        List<SysMenu> menus = menuMapper.selectMenuNormalAll();
        return getChildPerms(menus, 0);
    }

    @Override
    public List<MenuVo> selectMenusByUser(SysUser user) {
        List<SysMenu> menus;
        // 管理员显示所有菜单信息
        if (user.isAdmin()) {
            menus = menuMapper.selectMenuNormalAll();
        } else {
            menus = menuMapper.selectMenusByUserId(user.getId());
        }
        return getChildPerms(menus, 0);
    }

    /**
     * 根据父节点的ID获取所有子节点
     *
     * @param list     分类表
     * @param parentId 传入的父节点ID
     * @return String
     */
    private List<MenuVo> getChildPerms(List<SysMenu> list, long parentId) {
        List<MenuVo> returnList = new ArrayList<>();
        for (SysMenu t : list) {
            if (t.getParentId() == parentId) {

                MetaVo metaVo = new MetaVo();
                metaVo.setIcon(t.getIcon());
                metaVo.setTitle(t.getMenuName());

                MenuVo menuVo = new MenuVo();
                menuVo.setName(t.getMenuName());
                menuVo.setComponent(t.getComponent());
                menuVo.setPath(t.getUrl());
                menuVo.setRedirect(t.getRedirect());
                menuVo.setMeta(metaVo);

                returnList.add(menuVo);
                List<MenuVo> child = getChildPerms(list, t.getId());
                menuVo.setChildren(child);
            }
        }
        return returnList;
    }

    /**
     * 根据用户ID查询权限
     *
     * @param userId 用户ID
     * @return 权限列表
     */
    @Override
    public Set<String> selectPermsByUserId(Long userId) {
        List<String> perms = menuMapper.selectPermsByUserId(userId);
        Set<String> permsSet = new HashSet<>();
        for (String perm : perms) {
            if (StringUtils.isNotEmpty(perm)) {
                permsSet.addAll(Arrays.asList(perm.trim().split(",")));
            }
        }
        return permsSet;
    }

    /**
     * 根据用户ID查询权限
     *
     * @param user 用户
     * @return 权限列表
     */
    @Override
    public Set<String> selectPermsByUser(SysUser user) {
        Set<String> permsSet = new HashSet<>();
        if (user.isAdmin()) {
            permsSet.add("*:*:*");
        } else {
            List<String> perms = menuMapper.selectPermsByUserId(user.getId());
            for (String perm : perms) {
                if (StringUtils.isNotEmpty(perm)) {
                    permsSet.addAll(Arrays.asList(perm.trim().split(",")));
                }
            }
        }
        return permsSet;
    }

    @Override
    public List<TreeData> menuTreeData() {
        List<SysMenu> sysMenus = menuMapper.selectMenuAll();
        return getTreeData(sysMenus, 0);
    }

    @Override
    public List<TreeData> menuTreeSelectData() {
        List<SysMenu> sysMenus = menuMapper.selectMenuNormalAll();
        return getTreeData(sysMenus, 0);
    }

    @Override
    public boolean insertMenu(SysMenu menu) {
        return menuMapper.insertMenu(menu) > 0;
    }

    @Override
    public boolean updateMenu(SysMenu menu) {
        return menuMapper.updateMenu(menu) > 0;
    }

    @Override
    public boolean deleteMenuByIds(Long[] ids) {
        return menuMapper.deleteMenuByIds(ids) > 0;
    }

    @Override
    public List<SysMenu> menuTreeTableData() {
        List<SysMenu> sysMenus = menuMapper.selectMenuAll();
        return getTreeTableData(sysMenus, 0);
    }

    @Override
    public Map<String, Object> roleMenuTreeData(SysRole role) {
        Map<String, Object> map = new HashMap<>(2);
        map.put("treeData", menuTreeData());
        if (StringUtils.isNotNull(role) && StringUtils.isNotNull(role.getId())) {
            map.put("checked", menuMapper.selectMenuTree(role.getId()));
        }
        return map;
    }


    private List<TreeData> getTreeData(List<SysMenu> list, long parentId) {
        List<TreeData> returnList = new ArrayList<>();
        for (SysMenu t : list) {
            if (t.getParentId() == parentId) {
                TreeData treeData = new TreeData();
                treeData.setId(t.getId());
                treeData.setLabel(t.getMenuName());
                treeData.setOrderNum(t.getOrderNum());
                returnList.add(treeData);
                List<TreeData> child = getTreeData(list, t.getId());
                treeData.setChildren(child);
            }
        }
        return returnList;
    }


    /**
     * 根据父节点的ID获取所有子节点
     *
     * @param list     分类表
     * @param parentId 传入的父节点ID
     * @return String
     */
    private List<SysMenu> getTreeTableData(List<SysMenu> list, int parentId) {
        List<SysMenu> returnList = new ArrayList<>();
        for (SysMenu t : list) {
            // 一、根据传入的某个父节点ID,遍历该父节点的所有子节点
            if (t.getParentId() == parentId) {
                recursionFn(list, t);
                returnList.add(t);
            }
        }
        return returnList;
    }

    /**
     * 递归列表
     *
     * @param list
     * @param t
     */
    private void recursionFn(List<SysMenu> list, SysMenu t) {
        // 得到子节点列表
        List<SysMenu> childList = getChildList(list, t);
        t.setChildren(childList);
        for (SysMenu tChild : childList) {
            if (hasChild(list, tChild)) {
                // 判断是否有子节点
                for (SysMenu n : childList) {
                    recursionFn(list, n);
                }
            }
        }
    }

    /**
     * 得到子节点列表
     */
    private List<SysMenu> getChildList(List<SysMenu> list, SysMenu t) {
        List<SysMenu> tlist = new ArrayList<>();
        for (SysMenu n : list) {
            if (n.getParentId().longValue() == t.getId().longValue()) {
                tlist.add(n);
            }
        }
        return tlist;
    }

    /**
     * 判断是否有子节点
     */
    private boolean hasChild(List<SysMenu> list, SysMenu t) {
        return getChildList(list, t).size() > 0;
    }


    /**
     * 校验菜单名称是否唯一
     *
     * @param menu 菜单信息
     * @return 结果
     */
    @Override
    public String checkMenuNameUnique(SysMenu menu) {
        long menuId = StringUtils.isNull(menu.getId()) ? -1L : menu.getId();
        List<SysMenu> menuList = menuMapper.checkMenuNameUnique(menu.getMenuName(), menu.getParentId());
        if (menuList != null) {
            for (SysMenu sysMenu : menuList) {
                if (StringUtils.isNotNull(sysMenu) && sysMenu.getId() != menuId) {
                    return UserConstants.MENU_NAME_NOT_UNIQUE;
                }
            }
        }
        return UserConstants.MENU_NAME_UNIQUE;
    }

}
